package com.lz.netty.consumer.project.netty;

import com.alibaba.fastjson2.JSON;
import com.lz.netty.consumer.common.utils.DateUtils;
import com.lz.netty.consumer.common.utils.SpringBeanUtils;
import com.lz.netty.consumer.project.netty.util.MsgUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.socket.SocketChannel;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;


/**
 * 客户端连接信息 读取信息
 * @author Administrator
 */
@Component
@Slf4j
public class MyClientInHandler extends ChannelInboundHandlerAdapter {


    @Resource
    NettyClient nettyClient;

    /**
     * 当客户端主动链接服务端的链接后，这个通道就是活跃的了。也就是客户端与服务端建立了通信通道并且可以传输数据
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        //保存频道
        ChannelStore.bind(ctx, String.valueOf(ctx.channel().id()));
        SocketChannel channel = (SocketChannel) ctx.channel();
        log.info("客户端链接报告开始");
        log.info("客户端链接报告信息：本客户端链接到服务端。channelId：{}", channel.id());
        log.info("客户端链接报告IP:{}", channel.localAddress().getHostString());
        log.info("客户端链接报告Port:{}", channel.localAddress().getPort());
        log.info("客户端链接报告完毕");
        //通知服务端链接建立成功
        String str = "客户端段连接成功回调通知服务端，时间：" + DateUtils.getCurr_YYYY_MM_DD_HH_MM_SS_SSS() + ", 地址：" + channel.localAddress().getHostString();
        ctx.writeAndFlush(MsgUtil.buildMsg(channel.id().toString(), str));
    }

    /**
     * 当客户端主动断开服务端的链接后，这个通道就是不活跃的。也就是说客户端与服务端的关闭了通信通道并且不可以传输数据
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        //保存频道
        ChannelStore.closeAndClean(ctx);
        log.warn("客户端断开链接{}", ctx.channel().localAddress().toString());
        log.warn("客户端开始尝试重新链接{}", ctx.channel().localAddress().toString());
        while (!reConnect()) {
            reConnect();
        }
        log.warn("客户端尝试重新链接成功{}", ctx.channel().localAddress().toString());
    }
    /**
     * 断开后重连
     */
    public boolean reConnect() {
        try {
            //休眠3秒 避免CPU空转
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return SpringBeanUtils.getBean(NettyClient.class).start();
    }

    /**
     * 客户端读取传递过来的消息
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        //接收msg消息
        log.info("客户端接收到消息类型：{}，时间:{}", msg.getClass(), DateUtils.getCurr_YYYY_MM_DD_HH_MM_SS_SSS());
        log.info("客户端消息内容：{}，时间:{}", JSON.toJSONString(msg), DateUtils.getCurr_YYYY_MM_DD_HH_MM_SS_SSS());
    }

    /**
     * 抓住异常，当发生异常的时候，可以做一些相应的处理，比如打印日志、关闭链接
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        ctx.close();
        log.error("客户端Handler异常信息：{}\r\n", cause.getMessage());
    }

}
